# 赋予人格化，模仿人类

from DrissionPage.common import Actions
from DrissionPage.common import Settings
from DrissionPage.items import SessionElement
from DrissionPage.items import ChromiumElement
from DrissionPage.items import ShadowRoot
from DrissionPage.items import NoneElement
from DrissionPage.items import ChromiumTab
from DrissionPage.items import MixTab
from DrissionPage.items import ChromiumFrame
from DrissionPage import ChromiumOptions

import random,re
from utils.CDPClient import WebSocketCDPClient, CDP




def generate_array():
    # 随机生成一个中间较大的数字
    middle = random.randint(20, 40)
    
    # 保证两头的数字较小，并随机生成
    start = random.randint(5, 15)
    end = random.randint(5, 15)
    
    # 计算剩余两个数字的和，使总和为100
    remaining_sum = 100 - (start + end + middle)
    
    # 这两个数字要尽量符合较小较大的规则，可以通过随机数生成
    second = random.randint(remaining_sum // 2, remaining_sum)
    fourth = remaining_sum - second
    
    # 排列顺序: start, second, middle, fourth, end
    result = [start, second, middle, fourth, end]
    
    # 返回结果
    return result



        


class  _SaoTab(ChromiumTab):
        # def __init__(self, browser, tab_id):
        #     # Settings.singleton_tab_obj = True
        #     pass
            
        def work(self):
            print("work")
        def  ele(self, locator, index=1, timeout=None):


            if type(locator)==str and locator.startswith('<'):                
                locator=Use.raw(locator)

            print(f"变异的---  {locator} ")
            return super().ele(locator, index, timeout)
        

        def fetch_json(self,url:str,config_dict:dict={}):  #https://zh.javascript.info/fetch
            fetch_code=r'''fetch("网址", 配置);'''.replace('网址',url).replace('配置',str(config_dict))
            response_code='''
            async function getdata(){
                var res = await fetch_code;
                let data = await res.json();
                return data;
                console.log(data);
            }
            return getdata();
            '''.replace('fetch_code',fetch_code)
            print(response_code)
            info=self.run_js(response_code)
            return info
        

        

        def fetch_json_by_code(self,fetch_code:str):  #https://zh.javascript.info/fetch
            fetch_code=fetch_code
            response_code='''
            async function getdata(){
                var res = await fetch_code;
                let data = await res.json();
                return data;
                console.log(data);
            }
            return getdata();
            '''.replace('fetch_code',fetch_code)
            print(response_code)
            info=self.run_js(response_code)
            return info
        

        def table_to_dict(self, element: ChromiumElement,debug=False):
            table_data = {}

            # 如果元素是字符串类型，将其转换为元素对象
            if isinstance(element, str):
                element = self.ele(element)

            # 获取表头（thead）并提取所有列标题（th）
            thead_element = element.ele('t:thead')
            column_headers = [header.text for header in thead_element.eles("t:th")]
            if debug:
                print(column_headers)
            table_data["head"] = column_headers

            # 获取表体（tbody）中的所有行（tr）
            tbody_element = element.ele("t:tbody")
            rows = tbody_element.eles("t:tr")
            table_body = []

            for row in rows:
                row_data = [cell.text for cell in row.eles("t:td")]
                if debug:
                    print(row_data)                 
                table_body.append(row_data)

            table_data["body"] = table_body

            return table_data


        
        @property 
        def human_actions(self):
            return HumanActions(self)
        

        def mobile_mode(self, mode=True):
            if mode:
                # 设置为移动设备模式
                user_agents = {                   
                    "Chrome_Android": "Mozilla/5.0 (Linux; Android 12; Pixel 5 Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Mobile Safari/537.36",
                    "Safari_iOS": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1",
                    "Opera_Windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 OPR/97.0.4692.71"
                }
                
                # 设置用户代理
                ua = {
                    "method": "Network.setUserAgentOverride",
                    "params": {
                        "userAgent": user_agents["Chrome_Android"],  # 设置为 Android 浏览器的 User-Agent
                        "acceptLanguage": "en-US",  # 可选：指定 Accept-Language
                        "platform": "Win32"         # 可选：指定平台（Windows）
                    }
                }
                self.run_cdp(ua["method"], **ua["params"])

                # 设置设备模拟为移动模式
                zoom = {
                    "command": "Emulation.setDeviceMetricsOverride",
                    "parameters": {
                        "width": 360,                # 移动设备宽度
                        "height": 740,               # 移动设备高度
                        "deviceScaleFactor": 1,      # DPI 比例
                        "mobile": True,              # 设置为手机模式
                        "scale": 1                   # 页面缩放比例
                    }
                }
                self.run_cdp(zoom["command"], **zoom["parameters"])

            else:
                # 设置为桌面设备模式
                user_agents = {
                    "Chrome_Windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",

                    "Edge_Windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edge/110.0.1587.57"
                }
                
                # 设置为桌面浏览器的 User-Agent
                ua = {
                    "method": "Network.setUserAgentOverride",
                    "params": {
                        "userAgent": user_agents["Chrome_Windows"],  # 设置为桌面浏览器的 User-Agent
                        "acceptLanguage": "en-US",  # 可选：指定 Accept-Language
                        "platform": "Win32"         # 可选：指定平台（Windows）
                    }
                }
                self.run_cdp(ua["method"], **ua["params"])

                # 设置设备模拟为桌面模式
                zoom = {
                    "command": "Emulation.setDeviceMetricsOverride",
                    "parameters": {
                        "width": 1920,               # 桌面设备宽度（常见宽度为 1920px）
                        "height": 1080,              # 桌面设备高度（常见高度为 1080px）
                        "deviceScaleFactor": 1,      # DPI 比例
                        "mobile": False,             # 关闭手机模式
                        "scale": 1                   # 页面缩放比例
                    }
                }
                self.run_cdp(zoom["command"], **zoom["parameters"])


        def startJsonListener(self,content_contain=""):
            tab=self 
            # 初始化 WebSocket 客户端
            ws_client = WebSocketCDPClient(tab, debug=True)
            #设置过滤器
            if len(content_contain)>0:
                ws_client.filter_in_content=content_contain
            # 设置响应接收监听器
            ws_client.set_listener(CDP.Network.responseReceived, ws_client.received_data_and_save(type='json'))
            # 获取所有的数据包列表

class SaoTab():
    def __new__(cls,tab:ChromiumTab)->_SaoTab:
        # 启用多例：
        Settings.singleton_tab_obj = False
        borwser=tab._browser
        tab_id=tab.tab_id
        return _SaoTab(borwser,tab_id)              
    
      

                           



class HumanActions(Actions):
    def __init__(self, owner):
        super().__init__(owner)


    def move(self, offset_x = 0, offset_y = 0, duration = 0.5):
        xyd_list=[]

        if offset_x>0:
            aa=[a/100  for a in  generate_array()]
  
            xyd_list=[(offset_x*a,offset_y*a,duration*0.4) for a in aa]
        for i in xyd_list:
            super().move(i[0],i[1],i[2])
            # print(f"模拟人类行为，move {i[0]} {i[1]} {i[2]}")    

        return self
    
    def type(self, keys, interval = 1):
        return super().type(keys, interval)




# 工具类

class Use:
    @staticmethod
    def extract_text(s):
        # 直接使用正则表达式提取并返回结果
        return ''.join(re.findall(r'(?<=>)(.+?)(?=<)', s))

    @staticmethod
    def extract_attrs_value(input_string):
        # 直接返回匹配结果
        return re.findall(r'"[^"]+"', input_string)

    @staticmethod
    def extract_attrs_name(input_string):
        # 改进正则表达式以更精确地匹配属性名
        return re.findall(r'\b\w+(?==")', input_string)

    @staticmethod
    def extract_innertext(input_string):
        # 使用正则表达式简化内部文本提取
        match = re.search(r'>(.*?)<', input_string)
        return match.group(1) if match else ''

    @staticmethod
    def raw(input_str):
        input_str = input_str.strip()
        tag_name_match = re.match(r'<(\w+)', input_str)
        tag_name = tag_name_match.group(1) if tag_name_match else ''
        
        tag_attr_values = Use.extract_attrs_value(input_str)
        tag_attr_names = Use.extract_attrs_name(input_str)
        
        attr_all = ''.join([f'@@{name}={value}' for name, value in zip(tag_attr_names, tag_attr_values)])
        attr_all = attr_all.replace('"', '')
        
        txt = Use.extract_text(input_str)
        tag_txt = f'@@text()={txt}' if txt else ''
        
        transformed_str = f'tag:{tag_name}{attr_all}{tag_txt}'
        print(transformed_str)
        return transformed_str

if __name__ == '__main__':
    aa=[a/100  for a in  generate_array()]
    print(aa)



#  更多炸裂更新中... 关注  骚神网  https://wxhzhwxhzh.github.io/sao/  关注bilibili  视频号加粉丝一键三连


# 变异特性1.所见即所得的语法定位
# 变异特性2.完全模拟人类行为动作的动作链
# 变异特性3.彻底模仿移动端  动态变换
# 后续版本的新变异特性
#  动态切换IP代理 支持账号密码 登录    tab.change_proxy()
#  自动识别验证码  自动识别拼图验证码 和 滑动验证码 和 数字验证码     tab.auto_captcha() 
#  按照数据类型进行分类的数据监听 和 全浏览器数据监听 tab.data_listener()  browser.data_listener()    